package ntd.tool;

public class ToolCrc16 {

    /**
     * 一个字节包含位的数量 8
     */
    private static final int BITS_OF_BYTE = 8;

    /**
     * 多项式
     */
    private static final int POLYNOMIAL = 0xA001;

    /**
     * 初始值
     */
    private static final int INITIAL_VALUE = 0xFFFF;


    /**
     *
     * @param src	数据
     * @return
     */
    public static String crc16(String src) {
        int crc = 0x0000FFFF;
        short tc;
        char sbit;
        for (int i = 0; i < src.length(); i++) {
            tc = (short) (crc >>> 8);
            crc = ((tc ^ src.charAt(i)) & 0x00FF);
            for (int r = 0; r < 8; r++) {
                sbit = (char) (crc & 0x01);
                crc >>>= 1;
                if (sbit != 0)
                    crc = (crc ^ 0xA001) & 0x0000FFFF;
            }
        }
        String str=Integer.toHexString(crc);
        if(str.length()==3){
            return "0"+str.toUpperCase();
        }else if(str.length()==2){
            return "00"+str.toUpperCase();
        }else if(str.length()==1){
            return "000"+str.toUpperCase();
        }
        return str.toUpperCase();
    }
    /**
     * CRC16 编码
     * @param bytes 编码内容
     * @return 编码结果
     */
    public static String crc16(int[] bytes) {
        int res = INITIAL_VALUE;
        for (int data : bytes) {
            res = res ^ data;
            for (int i = 0; i < BITS_OF_BYTE; i++) {
                res = (res & 0x0001) == 1 ? (res >> 1) ^ POLYNOMIAL : res >> 1;
            }
        }
        return convertToHexString(revert(res));
    }

    /**
     * 翻转16位的高八位和低八位字节
     * @param src 翻转数字
     * @return 翻转结果
     */
    private static int revert(int src) {
        int lowByte = (src & 0xFF00) >> 8;
        int highByte = (src & 0x00FF) << 8;
        return lowByte | highByte;
    }

    private static String convertToHexString(int src) {
        return Integer.toHexString(src);
    }

    public static void main(String[] args) {
        int[] data = new int[]{0x01, 0x03, 0x01, 0xF4, 0x00, 0x02};
        System.out.println(ToolCrc16.crc16(data));
    }
}